﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Littlefish.Data;
using Littlefish.Model;

namespace Littlefish.Model.Objects
{
    public class Demographic : BaseBusinessObject<Data.Demographic, MainDataContext>
    {
        #region - Constructor -
        internal Demographic() : base() { }
        internal Demographic(MainDataContext context) : base(context) { }
        internal Demographic(MainDataContext context, Data.Demographic entity)
            : base(context)
        {
            this.Entity = entity;
        }
        #endregion

        #region - Public Properties -
        public int Id
        {
            get { return Entity.Id; }
        }
        /// <summary>
        /// Specifies whether the person is of Hispanic or Latino descent.
        /// </summary>
        public bool HispanicLatino
        {
            get { return Entity.HispanicLatino; }
            set { Entity.HispanicLatino = value; }
        }
        /// <summary>
        /// Persons Gender.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.Genders"/>
        public string Gender
        {
            get { return Entity.Gender; }
            set { Entity.Gender = value; }
        }
        /// <summary>
        /// Means by which the person's birth date was validated.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.BirthdateVerification"/>
        public string BrithdateVerification
        {
            get { return Entity.BirthdateVerification; }
            set { Entity.BirthdateVerification = value; }

        }
        /// <summary>
        /// The person's place of birth—like village, town, city etc.
        /// </summary>
        public string PlaceOfBirth
        {
            get { return Entity.PlaceOfBirth; }
            set { Entity.PlaceOfBirth = value; }
        }
        /// <summary>
        /// The county in which the person was born.
        /// </summary>
        public string CountyOfBirth
        {
            get{return Entity.CountyOfBirth;}
            set{Entity.CountyOfBirth = value;}
        }
        /// <summary>
        /// A list of countries which the person is a citizen of.
        /// </summary>
        public IEnumerable<string> CountriesOfCitizenship
        {
            get
            {
                List<string> countries = new List<string>();
                foreach (DemographicCountryCitenzenship country in Entity.CountryCitenzenships)
                {
                    countries.Add(country.Country);
                }
                return countries;
            }
        }
        /// <summary>
        /// A list of countries which the person is a residence of.
        /// </summary>
        public IEnumerable<string> CountriesOfResidency
        {
            get
            {
                List<string> countries = new List<string>();
                 foreach (DemographicCountryResidency country in  Entity.CountryResidencies)
                {
                    countries.Add(country.Country);
                }
                return countries;
            }
        }
        /// <summary>
        /// The person's state of birth.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.USPSAbbreviations"/>
        /// <seealso cref="Littlefish.Model.ExternalCodes.CanadianProvinces"/>
        public string StateOfBirth
        {
            get { return Entity.StateOfBirth; }
            set { Entity.StateOfBirth = value; }
        }
        /// <summary>
        /// The person's country of birth.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.CountryCodes"/>
        public string CountryOfBirth
        {
            get { return CountryOfBirth; }
            set { Entity.CountryOfBirth = value; }
        }
        /// <summary>
        /// Date the person first arrived in the country.
        /// </summary>
        public DateTime CountryArrivalDate
        {
            get { return Entity.CountryArrivalDate; }
            set { Entity.CountryArrivalDate = value; }
        }
        /// <summary>
        /// The person's citizenship status.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.CitezenshipStatus"/>
        public string CitizenshipStatus
        {
            get { return Entity.CitezenshipStatus; }
            set { Entity.CitezenshipStatus = value; }
        }
        /// <summary>
        /// Person's proficiency in English.
        /// </summary>
        public string EnglishProficiency
        {
            get { return Entity.EnglishProficiency; }
            set { Entity.EnglishProficiency = value; }
        }
        /// <summary>
        /// Setting/environment in which the person resides.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.DwellingArrangements"/>
        public string DwellingArrangement
        {
            get { return Entity.DwellingArrangementCode; }
            set { Entity.DwellingArrangementCode = value; }
        }
        /// <summary>
        /// Additional codes related to the persons dwelling arrangement.
        /// </summary>
        public IEnumerable<OtherCode> OtherDwellingArrangementCodes
        {
            get
            {
                List<OtherCode> codes = new List<OtherCode>();
                foreach (DwellingArrangementOtherCode code in Entity.DwellingArrangementOtherCodes)
                {
                    codes.Add(new OtherCode { Code = code.Code, Codeset = code.Codeset });
                }
                return codes;
            }
        }
        /// <summary>
        /// The person's marital status.
        /// </summary>
        /// <seealso cref="Littlefish.Model.ExternalCodes.MaritalStatus"/>
        public string MaritalStatus
        {
            get { return Entity.MartialStatus; }
            set { Entity.MartialStatus = value; }
        }
        #endregion

        #region - Public Methods -
        public bool AddCountryOfCitizenship(string countryCode)
        {
            bool success = false;
            if (ExternalCodes.CountryCodes.CodeExists(countryCode) && GetCountryOfCitezenship(countryCode) == null)
            {
                Entity.CountryCitenzenships.Add(new DemographicCountryCitenzenship { Country = countryCode.Trim().ToUpperInvariant() });
                success = true;
            }
            return success;
        }
        public bool RemoveCountryOfCitezenship(string countryCode)
        {
            bool success = false;
            DemographicCountryCitenzenship country = GetCountryOfCitezenship(countryCode);
            if (country != null)
            {
                if (country.LastEdit == null) //need to delete from context
                {
                    Context.DemographicCountryCitenzenships.DeleteOnSubmit(country);
                }
                else //Just delete from entity collection
                {
                    Entity.CountryCitenzenships.Remove(country);
                }
            }
            return success;
        }
        public bool AddCountryOfResidence(string countryCode)
        {
            bool success = false;
            if (ExternalCodes.CountryCodes.CodeExists(countryCode) && GetCountryOfResidence(countryCode) == null)
            {
                Entity.CountryResidencies.Add(new DemographicCountryResidency { Country = countryCode.Trim().ToUpperInvariant() });
                success = true;
            }
            return success;
        }
        public bool RemoveCountryOfResidence(string countryCode)
        {
            bool success = false;
            DemographicCountryResidency country = GetCountryOfResidence(countryCode);
            if (country != null)
            {
                if (country.LastEdit != null)
                    Context.DemographicCountryResidencies.DeleteOnSubmit(country);

                Entity.CountryResidencies.Remove(country);
                success = true;
            }
            return success;
        }
        public bool AddOtherDwellingArrangementCode(OtherCode code)
        {
            bool success = false;
            if (GetDwellingArrangementOtherCode(code) == null)
            {
                Entity.DwellingArrangementOtherCodes.Add(new DwellingArrangementOtherCode { Code = code.Code, Codeset = code.Codeset });
            }
            return success;
        }
        public bool RemoveOtherDwellingArrangmentCode(OtherCode code)
        {
            bool success = false;
            DwellingArrangementOtherCode otherCode = GetDwellingArrangementOtherCode(code);
            if (otherCode != null)
            {
                if (otherCode.LastEdit == null)
                {
                    Context.DwellingArrangementOtherCodes.DeleteOnSubmit(otherCode);
                }
                else
                {
                    Entity.DwellingArrangementOtherCodes.Remove(otherCode);
                }
            }
            return success;
        }
        #endregion

        #region - Private Methods -
        private DemographicCountryCitenzenship GetCountryOfCitezenship(string countryCode)
        {
            return Entity.CountryCitenzenships.FirstOrDefault(c => c.Country == countryCode.Trim().ToUpperInvariant());
        }
        private DemographicCountryResidency GetCountryOfResidence(string countryCode)
        {
            return Entity.CountryResidencies.FirstOrDefault(c => c.Country == countryCode.Trim().ToUpperInvariant());
        }
        private DwellingArrangementOtherCode GetDwellingArrangementOtherCode(OtherCode code)
        {
            return Entity.DwellingArrangementOtherCodes.FirstOrDefault(oc => oc.Codeset == code.Codeset && oc.Code == code.Code);
        }
        #endregion

        #region - Overriden Methods -
        protected override void CheckValidationRules(Littlefish.Data.Demographic entity)
        {
            //-- Set default date values
            if (entity.BirthDate == DateTime.MinValue)
                entity.BirthDate = App.MIN_DATE;

            if (entity.CountryArrivalDate == DateTime.MinValue)
                entity.CountryArrivalDate = App.MIN_DATE;

            if (!string.IsNullOrEmpty(entity.DwellingArrangementCode))
                ValidationErrors.Assert(ExternalCodes.DwellingArrangements.CodeExists(entity.DwellingArrangementCode), "DwellingArrangementCode is not valid");
            else
                ValidationErrors.Assert(string.IsNullOrEmpty(entity.DwellingArrangementCode), "Cannot be blank", "DwellingArrangementCode");

        }
        #endregion

        #region - Static Methods -
        public static Demographic CreateDemographic()
        {
            return CreateDemographic(null, null);
        }
        public static Demographic CreateDemographic(BusinessObjectOptions options)
        {
            return CreateDemographic(null, options);
        }
        public static Demographic CreateDemographic(MainDataContext context)
        {
            return CreateDemographic(context, null);
        }
        public static Demographic CreateDemographic(MainDataContext context, BusinessObjectOptions options)
        {
            Demographic demographic = new Demographic(context);
            if (options != null)
                demographic.Options = options;

            demographic.NewEntity();
            return demographic;
        }

        public static Demographic GetDemographic(int id)
        {
            return GetDemographic(id, null, null);
        }
        public static Demographic GetDemographic(int id, BusinessObjectOptions options)
        {
            return GetDemographic(id, null, options);
        }
        public static Demographic GetDemographic(int id, MainDataContext context)
        {
            return GetDemographic(id, context, null);
        }
        public static Demographic GetDemographic(int id, MainDataContext context, BusinessObjectOptions options)
        {
            Demographic demographic = new Demographic(context);

            if (options != null)
                demographic.Options = options;

            demographic.Load(id);
            return demographic;
        }
        public static IEnumerable<Demographic> GetDemographics()
        {
            MainDataContext context = new MainDataContext();
            List<Demographic> demographics = new List<Demographic>();
            var entities = from d in context.Demographics
                           orderby d.Id
                           select d;

            foreach (Data.Demographic d in entities)
            {
                Demographic dem = new Demographic(context);
                dem.Entity = d;
                demographics.Add(dem);
            }
            return demographics;
        }
        #endregion
    }
}
